/*********************************************************************************
*  Seg 2501, hiver 2002 Devoir # 4
*
*  fichier Banque.java
*  simulator controller and statistics reporting 
*
*  @author  Anne Bertrand
*  @author  Robin Tropper
*  @refactoredBy Robin Tropper  B.A.Sc.
*
*  BUG : it sometimes happened (past) that cashiers could not see that "the bank
*  is closed" => result: infinite loop when a cashier is looking for the next client.
*  => SHOULD BE fixed, but difficult to formally prove.
*  
**********************************************************************************/

import java.util.*;

public class Bank {

 	private static int numCashiers = 3;
 	private static long duration = 3600;
 	
 	private static boolean quittingTime = false;

 	static Timer finished = new Timer();	//time limit for entire simulation
	static ClientQueue enterpriseQueue = new ClientQueue(300,100,duration, " Entreprise");
	static ClientQueue individualsQueue = new ClientQueue(50,50,duration," Individual");

	/**
	 * By default, there is only one queue for enterprises and one queue for individuals.
	 * The following method aims to favor scalability where multiple queues and multiple
	 * priorities are allowed; i.e. an unknown number of queues where the priorities must
	 * still be respected.
	 * 
	 * @return : the liste of queues in descending order of priority.
	 * In other words, looping throught the list respects the priorities. 
	 */
	public static synchronized List<ClientQueue> showQueues(){
		List<ClientQueue> queueList = new ArrayList<ClientQueue>();
		queueList.add(0, enterpriseQueue);
		queueList.add(1, individualsQueue);
		return queueList;
	}//fin montreFiles
	
	public static boolean isClosed(){
		return quittingTime;
	}//fin getCloture
	
//#####
// main
//#####
	public static void main(String[] args) {
		System.out.println("Simulation for "+numCashiers+" cashiers over "+
								duration/600+" hours.");
		System.out.println("Please wait "+duration/600+
											" seconds for the results");
		finished.schedule(new Terminer(), duration);
		System.out.println("NUMBER OF CASHIERS "+numCashiers);
		for (int k=0; k<numCashiers; k++) {
			new Cashier(k);
		}
	}//fin du main

	static class Terminer extends TimerTask{
  		public void run(){
  			quittingTime = true;
  			finished.cancel();//stop the Timer : other objects may be using it

  			long enterprisesWaiting = enterpriseQueue.queueSize();			//non-served enterprises
	  		long individualsWaiting = individualsQueue.queueSize();			//non-served indivituals
			long enterprisesServed = enterpriseQueue.getNumClientsServed();
			long individualsServed = individualsQueue.getNumClientsServed();
			long enterprisesThatCame = enterprisesWaiting+enterprisesServed;
			long individualsThatCame = individualsWaiting+individualsServed;
			long totalServed = enterprisesServed+individualsServed;
			long totalClients = totalServed+enterprisesWaiting+individualsWaiting;
			long meanWaitTimeEnterprises=0;
			long meanWaitIndividuals=0;
	  		System.out.println("\n"+totalClients+"Total visitors.");
	  		System.out.println(numCashiers+" Cashiers to serve them.\n");
	  		System.out.println(enterprisesThatCame+" enterprises that showed-up.");
	  		System.out.println(individualsThatCame+" individuals that showed-up.");
	  		System.out.println("Entreprises not served :" + enterprisesWaiting);
	  		System.out.println("Individuals not served :" + individualsWaiting);
			System.out.println("\tTotal clients served: "+totalClients);
			System.out.println("Entreprises served: "+enterprisesServed);
			System.out.println("Individuals served: "+individualsServed);
			if ((meanWaitTimeEnterprises=enterpriseQueue.getMeanWaitingTime())!=0) {
				System.out.println("\nMean waiting time for enterprises: "+
										meanWaitTimeEnterprises/10+" minutes");
			} else { System.out.println("No enterprises served.");}
			if ((meanWaitIndividuals=individualsQueue.getMeanWaitingTime())!=0) {
				System.out.println("Mean waiting time for individuals: "+
										meanWaitIndividuals/10+" minutes\n");
			} else { System.out.println("No individuals served.");}
	  		System.exit(0);
  		}//fin du run
  	}//fin du TimerTask

}//fin de la classe Banque